Unique string value processing from links

Hi all,

I have a module that collects together batches of requirements into "Features" (capabilities). The requirements are linked to the features from the requirements module. The Requirements module, contains an attribute for "Change Requests" that affect a requirement. I want to be able to show a list of CRs that affect each feature from the features module.

I have tried to write some layout DXL to display only unqiue references to CRs (as using the trace wizard I get loads of duplicate CR references displayed as a CR can effect more than one requirement). However, It does not seem to work. Just wondering if anyone can spot any glaring errors.

Link outgoinglink

Module m = current
Module targetreqmod

Object targetreqobj

string targetreqmodname
string s = null
string buffer = null

Array a = create(1,1)

int i = 0
int count

bool duplicate = false

for outgoinglink in obj -> "*" do {
            
    ModName_ smname = target outgoinglink
            
    // Determine module name that the target link is a member of
    targetreqmodname = fullName(smname)
        
    targetreqobj = target outgoinglink
            
    if (targetreqmodname == "/NTIS /Level 1 - System/Requirements/NTIS System Requirements") {
            
        // Store the contents of NTIS Chnage Reference for the current outgoing link in string s
        s = targetreqobj."NTIS Change Reference"
            
        // If this is the first linked object, store the contents of s in array a
        if (i == 0) {
            put(a, s, i, 0)
            display s
        }
        // If this is not the first linked object, compare the contents of a with s. If s is not original value (a duplicate),
        // skip storing it in array a. However, if it is an original value, store in array a and display s.
            
        else {
            duplicate = false
            for (count = 0; count <= i; count++){
                buffer = (string get(a, count, 0))
                if (buffer == s) {
                    duplicate = true
                }
            }
            if (duplicate == false) {
                put(a, s, i, 0)
                display s
            }
        }
    }
        
    // Increment i each time a new link is processed
    i++
}

delete a

 

Thanks,

 

Alex


AlexBeach - Thu Aug 29 06:19:02 EDT 2013

Re: Unique string value processing from links
GregM_dxler - Thu Aug 29 09:39:14 EDT 2013

Hi Alex,

I noticed a couple of things:

s = targetreqobj."NTIS Change Reference"
should include a "" at the end.  I think this ensures to save the value as a string.  I don't remember the particulars when you need it.  I just know that if you always put it in, it works.

Should the i++ be in the duplicate==false section instead of outside the for loop?  Otherwise, your incrementing the index for every link instead of incrementing every time you add a new value to the array.

The assumption here is that "NTIS Change Reference" will only contain a single value.  We have a list of CRs in a similar attribute.

The other assumption is that your target module is open.

Hope this helps a little,

Greg

Re: Unique string value processing from links
llandale - Thu Aug 29 12:31:12 EDT 2013

if the requirement value for "NTIS Change Reference" may contain only a single CR reference, then you can let the native "Skip" feature to ignore duplicates:

  • s = targetreqobj."NTIS Change Reference"
  • put(skpCRs, s, s)
  • <<Delete rest of code down to "i++">>

After your link loop:

  • for s in skpCRs do{display s}

if a requirement may have more than one CR, then you'll need to parse the value separated by delimiters (?comma space?) and put each delimited value in the Skip.

-Louie

Greg is right, you have a  "i" logical problem in what you have written.  Move "i++" right after the "put" (or merge them: <put(a, s, i++, 0)>>), and I think "Count < i" instead of "<=".  But I suggest you get rid of all that.

Greg is slightly wrong here:  <<s = targetreqobj."NTIS Change Reference">> is correct.  "o.Name" is indeed a variable of type "Attr__" and specifically is NOT the retrieved value.  However, "string = o.Name" specifically retrieves the value and stores in the string; I think the only time it auto-retrieves.  You would need to convert the "Attr__" into a retrieved value when it is not the only thing on the right side of an equal sign: <<if (o.Name "" != "") then...>>  When you "concatenate" an "Attr__" with a string, it means retrieve then concatenate: <<o.Name "">>

 

 

Re: Unique string value processing from links
AlexBeach - Fri Aug 30 03:22:06 EDT 2013

llandale - Thu Aug 29 12:31:12 EDT 2013

if the requirement value for "NTIS Change Reference" may contain only a single CR reference, then you can let the native "Skip" feature to ignore duplicates:

  • s = targetreqobj."NTIS Change Reference"
  • put(skpCRs, s, s)
  • <<Delete rest of code down to "i++">>

After your link loop:

  • for s in skpCRs do{display s}

if a requirement may have more than one CR, then you'll need to parse the value separated by delimiters (?comma space?) and put each delimited value in the Skip.

-Louie

Greg is right, you have a  "i" logical problem in what you have written.  Move "i++" right after the "put" (or merge them: <put(a, s, i++, 0)>>), and I think "Count < i" instead of "<=".  But I suggest you get rid of all that.

Greg is slightly wrong here:  <<s = targetreqobj."NTIS Change Reference">> is correct.  "o.Name" is indeed a variable of type "Attr__" and specifically is NOT the retrieved value.  However, "string = o.Name" specifically retrieves the value and stores in the string; I think the only time it auto-retrieves.  You would need to convert the "Attr__" into a retrieved value when it is not the only thing on the right side of an equal sign: <<if (o.Name "" != "") then...>>  When you "concatenate" an "Attr__" with a string, it means retrieve then concatenate: <<o.Name "">>

 

 

Hi all,

Thanks for the replies. It sort of worked as is, by luck more than anything. However, (as you both pointed out) the reason I thought it didn't work is because the CR attribute can have more than one CR in it. These are separated by <<carridge returns>>. How do I parse a value for a <<carridge return>>?

Count <= i was definiately a problem. I have moved the i++ too. Thanks for that.

 

Just got the skip list stuff working too. Now to figure out the parsing.

 

Thanks again.

Re: Unique string value processing from links
llandale - Fri Aug 30 10:45:41 EDT 2013

AlexBeach - Fri Aug 30 03:22:06 EDT 2013

Hi all,

Thanks for the replies. It sort of worked as is, by luck more than anything. However, (as you both pointed out) the reason I thought it didn't work is because the CR attribute can have more than one CR in it. These are separated by <<carridge returns>>. How do I parse a value for a <<carridge return>>?

Count <= i was definiately a problem. I have moved the i++ too. Thanks for that.

 

Just got the skip list stuff working too. Now to figure out the parsing.

 

Thanks again.

I think this works.  Comment feedback welcome.

  • // Main:
  • bufValue = o.Whatever
  • int Offset = 0
  • string Delims = " ,\n"  // space Comma EOL
  • while (Offset >= 0)
  • {  Entry = fGetEntry_Next(bufValue, Delims, Offset)
  •    if (Offset < 0) continue
  •    if (null Entry) continue
  •    deal with Entry
  • }
     
  • // Library functions follow, which I guess should be at the top of the script

//***************************************
int fFindAny_Next(Buffer in_bufList, string in_Characters, int in_OffsetStart)
{  // Starting from the Starting offset in the Buffer, find the position of the 1st of ANY
 // of the search Characters
 // Return -1 if not found
 // Note: whereas "fGetOffset()" finds the position of the ENTIRE sub-string,
 // this function finds ANY of the search characters.
 // Generally "in_Characters" represent "Delimiters"

 int iPosition, iChar,
  iLength_Buff = length(in_bufList),
  iLength_Chars = length(in_Characters)
 char c

 for (iPosition=in_OffsetStart; iPosition<iLength_Buff; iPosition++)
 {  c = in_bufList[iPosition]
    for (iChar=0; iChar<iLength_Chars; iChar++)
    {  if (c == in_Characters[iChar]) then return(iPosition)
    } // end checking each Character
 } // end looking for the next position
 return(-1)
} // end fFindAny_Next()

//---------------------------------------
int fFindAny_Next(string in_String,  in_Characters, int in_OffsetStart)
{ // Overloaded, accept string input
 fSetEmpty(lg_bufTemp_Variables)
 lg_bufTemp_Variables = in_String
 return(fFindAny_Next(lg_bufTemp_Variables,  in_Characters, in_OffsetStart))
} // end overloaded fFindAny_Next(string)

//***************************************
string fGetEntry_Next(Buffer in_bufRawList, string in_Delims, int &inout_Offset_RawList)
{ // Get the next valid "Entry" from  the RawList starting from the inout_Offset_RawList
 // Offset should originally be zero (1st valid position in RawList)
 // Update the inout_Offset_RawList pointing to after the Entry; ready for this function to be called
 // again in some loop.
 // When this function updates inout_Offset_RawList to -1; then the RawList has been completely parsed
 // "Entries" are separated by ANY of the Characters in the in_Delims variable (such as ",;\n"). 
 // The start and end of the in_bufRawList are considered delimiters; thus a string with no in_Delims will return that string.
 //
 // Note: user may want to set in_Delims to white space cl_White or cl_Delims.
 // User will probably want to ignore null return values (meaning two delims in a row were detected)

 // See function Skip fSplitList_Ordered() below for a good example of use.

 int    Length_RawList     = length(in_bufRawList)
 int    Offset_Delim, Length_Delims = length(in_Delims)
 int    iAttr, iDelim, Offset_Out  = inout_Offset_RawList
 string Entry

 if (Offset_Out < 0)  then return("") // List exhausted previously.  Probably calling error
 if (Offset_Out+1 > Length_RawList)
 {  inout_Offset_RawList = -1  // Completely done with this RawList
    return("")
 }

 Offset_Delim = fFindAny_Next(in_bufRawList, in_Delims, Offset_Out)
  //print "\t++ Off-Delim: " Offset_Delim "\tOff-Out: " Offset_Out "\n"

 if (Offset_Delim < 0)
 {    // No in_Delims in in_bufRawList.  Return entire in_bufRawList
    Entry     = in_bufRawList[Offset_Out:]
    Offset_Out = -1   // Done with list
 } // end no delims found
 else
 {   // A Delim is Found
    if (Offset_Delim == 0) //
    then Entry   = ""  // a Delim at start of in_bufRawList
    else Entry   = in_bufRawList[Offset_Out:Offset_Delim-1]
    Offset_Out = Offset_Delim+1
 } // end yes a delim found
 inout_Offset_RawList = Offset_Out
 return(Entry)
} // end fGetEntry_Next(Buffer)

-Louie